#ifndef QUANTIZER_H
#define QUANTIZER_H

#include <QColor>
#include <QHash>
#include <QList>
#include <QObject>

namespace WingGif {
class Quantizer : public QObject {
  Q_OBJECT

  Q_PROPERTY(int depth READ depth WRITE setDepth)
  Q_PROPERTY(int maxColors READ maxColors WRITE setMaxColors)
  Q_PROPERTY(int maxColorsWithTransparency READ maxColorsWithTransparency WRITE
                 setMaxColorsWithTransparency)
  Q_PROPERTY(QVector<QColor> colorTable READ colorTable WRITE setColorTable)
  Q_PROPERTY(
      QColor transparentColor READ transparentColor WRITE setTransparentColor)
  Q_PROPERTY(uchar transparentColorIndex READ transparentColorIndex)

protected:
  Quantizer(bool singlePass, QObject *parent = nullptr);

public:
  int depth();
  void setDepth(int value);

  int maxColors();
  bool setMaxColors(int value);

  int maxColorsWithTransparency();
  void setMaxColorsWithTransparency(int value);

  QVector<QColor> colorTable();
  void setColorTable(QVector<QColor> value);

  QColor transparentColor();
  void setTransparentColor(QColor value);

  // TODO: The index of the transparent color.
  // Not always MaxColors - 1, since the color table size is ^2 (...64, 128,
  // 256). When the user selects a value that doesn't fit nicely in one of those
  // spots (like 200), we can avoid wasting one color position.
  uchar transparentColorIndex();

  QByteArray quantize(QByteArray pixels, bool secondPassOnly = false);

  virtual void firstPass(QByteArray pixels);

  QVector<QColor> getPalette();

  virtual QByteArray parallelSecondPass(QByteArray pixels);
  virtual QByteArray secondPass(QByteArray pixels);

protected:
  // pixel: The pixel to quantize
  virtual void initialQuantizePixel(QColor pixel);
  // Override this to process the pixel in the first pass of the algorithm
  // This function need only be overridden if your quantize algorithm needs two
  // passes, such as an Octree quantizer.

  // pixel: The pixel to quantize
  virtual uchar quantizePixel(QColor pixel) = 0;
  // Override this to process the pixel in the second pass of the algorithm
  // return : The quantized value

  virtual QVector<QColor> buildPalette() = 0;
  // Retrieve the palette for the quantized image
  // return : The new color palette

private:
  bool _singlePass;
  // Flag used to indicate whether a single pass or two passes are needed for
  // quantization.

  QHash<int, int> _colorMap;
  // Lookup table that holds the already calculated indexes for the colors.

  int _depth = 4;
  // The image depth.

  int _maxColors = 256;
  // The maximum color count.

  int _maxColorsWithTransparency;
  // The maximum color count, without counting with the transparent color.

  QVector<QColor> _colorTable;
  // The calculated color table of the image.

  QColor _transparentColor;
  // The color marked as transparent.
};

} // namespace WingGif

#endif // QUANTIZER_H
